package cool.lichuan.common.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.util.Base64Utils;

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Security;

@Slf4j
public class AESUtil {
    /**
     * 算法/模式/补码方式
     */
    public static final String AES_CBC_PKCS7 = "AES/CBC/PKCS7Padding";

    /**
     * 解决java不支持AES/CBC/PKCS7Padding模式解密
     */
    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * 加密 + Base64
     *
     * @param iv 初始向量
     */
    public static String encryptString(byte[] data, String key, String iv) throws Exception {
        SecretKey secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), AES_CBC_PKCS7);
        Cipher cipher = Cipher.getInstance(AES_CBC_PKCS7);
        // CBC模式，需要向量iv，增加算法强度
        IvParameterSpec spec = new IvParameterSpec(iv.getBytes());
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, spec);
        byte[] bytes = cipher.doFinal(data);
        return new String(Base64Utils.encode(bytes));
    }

    /**
     * 解密 + Base64
     *
     * @param iv 初始向量
     */
    public static String decryptString(byte[] data, String key, String iv) throws Exception {
        SecretKey secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), AES_CBC_PKCS7);
        Cipher cipher = Cipher.getInstance(AES_CBC_PKCS7,"BC");
        IvParameterSpec spec = new IvParameterSpec(iv.getBytes());
        cipher.init(Cipher.DECRYPT_MODE, secretKey, spec);
        byte[] bytes = cipher.doFinal(data);
        return new String(bytes, "UTF-8");
    }

    private  static final String AES="AES";
    /**
     * AES加密
     * @param content
     * @param pkey
     * @return
     * @throws DecoderException
     */
    public static byte[] encrypt(String content, String pkey,String iv) throws Exception {
        try {
            String private_key=pkey;
            byte[] encodeFormat=null;
            try {
                //秘钥 Hex解码为什么秘钥要进行解码，因为秘钥是某个秘钥明文进行了Hex编码后的值，所以在使用的时候要进行解码
                encodeFormat = Hex.decodeHex(private_key.toCharArray());
            } catch (DecoderException e) {
                e.printStackTrace();
            }
            SecretKey secretKeySpec = new SecretKeySpec(pkey.getBytes(StandardCharsets.UTF_8), AES_CBC_PKCS7);

            // Cipher对象实际完成加密操作
            Cipher cipher = Cipher.getInstance(AES_CBC_PKCS7);
            // 加密内容进行编码
            byte[] byteContent = content.getBytes("UTF-8");
            // 用密匙初始化Cipher对象
            IvParameterSpec spec = new IvParameterSpec(iv.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec,spec);
            // 正式执行加密操作
            byte[] result = cipher.doFinal(byteContent);
            return result;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return null;
    }
}